package nacgraphs;

import java.awt.Dimension;
import java.util.HashMap;
import java.util.List;
import java.util.regex.Pattern;
import javax.swing.JOptionPane;

public final class MainFrame extends javax.swing.JFrame
{
    private GraphManager graphManager;

    /**
     * Creates new form MainFrame
     */
    public MainFrame()
    {
        initComponents();
        
        graphManager = new GraphManager(new Dimension(graphPanel.getWidth(), graphPanel.getHeight()));

        graphPanel.add(graphManager.getVisualizationViewer());
        
        log((String) filterComboBox.getSelectedItem());
        
        setVisible(true);
    }
    
    private boolean validateRm(int rm)
    {
        return validateRm(String.valueOf(rm));
    }
    
    private boolean validateRm(String rm)
    {
        return Pattern.matches("^[0-9]{5}$", rm);
    }
    
    private void alert(String text)
    {
        alert("Mensagem!", text);
    }
    
    private void alert(String title, String text)
    {
        Object[] options = {"OK"};
        
        JOptionPane.showOptionDialog(this, text, title, JOptionPane.PLAIN_MESSAGE, JOptionPane.QUESTION_MESSAGE, null, options, options[0]);
    }
    
    private void log(String filter)
    {
        log(filter, "");
    }
    
    private void log(String filter, String text)
    {
        String fullText = "Filtro atual: " + filter + "\n" + text;
        
        logTextArea.setText(fullText);
    }
    
    private void removeFilter()
    {
        removeFilter(null);
    }
    
    private void removeFilter(String message)
    {
        if(message != null)
        {
            alert(message);
        }
        
        filterComboBox.setSelectedIndex(0);
        graphManager.removeFilter();
        log((String) filterComboBox.getSelectedItem());
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        filterLabel = new javax.swing.JLabel();
        filterComboBox = new javax.swing.JComboBox();
        graphPanel = new javax.swing.JPanel();
        baseRmLabel = new javax.swing.JLabel();
        baseRmTextField = new javax.swing.JTextField();
        jScrollPane1 = new javax.swing.JScrollPane();
        logTextArea = new javax.swing.JTextArea();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("FIAP NAC - Grafos");
        setResizable(false);

        filterLabel.setText("Filtro:");

        filterComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Nenhum", "Menor caminho", "Não contatado(s)", "Intermediários", "Contatado(s)" }));
        filterComboBox.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                filterComboBoxActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout graphPanelLayout = new javax.swing.GroupLayout(graphPanel);
        graphPanel.setLayout(graphPanelLayout);
        graphPanelLayout.setHorizontalGroup(
            graphPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 0, Short.MAX_VALUE)
        );
        graphPanelLayout.setVerticalGroup(
            graphPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 596, Short.MAX_VALUE)
        );

        baseRmLabel.setText("Base RM: ");

        baseRmTextField.setHorizontalAlignment(javax.swing.JTextField.CENTER);
        baseRmTextField.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                baseRmTextFieldActionPerformed(evt);
            }
        });

        logTextArea.setEditable(false);
        logTextArea.setColumns(20);
        logTextArea.setRows(5);
        jScrollPane1.setViewportView(logTextArea);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(baseRmLabel)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(baseRmTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 80, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(516, 516, 516)
                        .addComponent(filterLabel)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(filterComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 320, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(0, 0, Short.MAX_VALUE))
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                            .addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(graphPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                        .addContainerGap())))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(filterLabel)
                    .addComponent(filterComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(baseRmLabel)
                    .addComponent(baseRmTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(graphPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 166, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap())
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void filterComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_filterComboBoxActionPerformed
        // TODO add your handling code here:
        
        String baseRm = (String) baseRmTextField.getText();
        
        if(baseRm.length() == 0)
        {
            alert("Por favor, informe o RM base.");
            
            filterComboBox.setSelectedIndex(0);
            
            baseRmTextField.requestFocus();
        }
        else if(!validateRm(baseRm))
        {
            alert("O RM base está inválido.");
            
            filterComboBox.setSelectedIndex(0);
            
            baseRmTextField.requestFocus();
        }
        else
        {
            if(filterComboBox.getSelectedIndex() == 1)
            {
                String rm = (String) JOptionPane.showInputDialog(this, "Informe o RM alvo", (String) filterComboBox.getSelectedItem(), JOptionPane.PLAIN_MESSAGE, null, null, null);

                if(rm != null)
                {
                    if(!validateRm(rm))
                    {   
                        removeFilter("RM inválido!\nAção desfeita.");
                    }
                    else
                    {
                        int sourceRm = Integer.valueOf(baseRm);
                        int targetRm = Integer.valueOf(rm);
                        
                        HashMap<Integer, GraphVertex> graphVertexes = graphManager.getGraphView().getGraphVertexes();
                        
                        if(graphVertexes.containsKey(sourceRm) && graphVertexes.containsKey(targetRm))
                        {
                            if(sourceRm != targetRm)
                            {
                                List<GraphEdge> shortestPath = graphManager.calculateShortestPath(sourceRm, targetRm);

                                String log = "De: " + sourceRm + "\nAté: " + targetRm + "\nSaltos: " + shortestPath.size() + "\n";

                                log += "Trajeto: ";

                                if(shortestPath.size() > 0)
                                {

                                    log += sourceRm;
                                }
                                else
                                {
                                    log += "não há como contatar";
                                }


                                for(int i = 0, len = shortestPath.size(); i < len; i++)
                                {   
                                    log += "->" + shortestPath.get(i).getTargetStudent().getRm();
                                }

                                log((String) filterComboBox.getSelectedItem(), log);
                            }
                            else
                            {
                                removeFilter("RMs (base e alvo) iguais! Você já está em seu \"destino\".");
                            }
                        }
                        else
                        {
                            removeFilter("Ambos os RMs devem conter no grafo. (Base RM e Alvo RM)");
                        }
                    }
                }
                else
                {
                    removeFilter("Ação desfeita.");
                }
            }
            else if(filterComboBox.getSelectedIndex() == 2)
            {
                int sourceRm = Integer.valueOf(baseRm);
                
                List<GraphVertex> untouchableVertexes = graphManager.calculateUntouchableVertexes(sourceRm);
                
                String log = "A partir de: " + sourceRm + "\nNão contatado(s): ";
                
                if(untouchableVertexes.isEmpty())
                {
                    log += "todos RMs são contatado(s)";   
                }
                else
                {
                    for(int i = 0, len = untouchableVertexes.size(); i < len; i++)
                    {   
                        log += untouchableVertexes.get(i).getRm();
                        
                        if(i < len - 1)
                        {
                            log += ", ";
                        }
                    }
                }
                
                log += "\nTotal: " + untouchableVertexes.size() + " não contatado(s)";
                
                log((String) filterComboBox.getSelectedItem(), log);
            }
            else if(filterComboBox.getSelectedIndex() == 4)
            {
                String[] options = new String[] {"1", "2", "3", "4", "5"};
                
                String option = (String) JOptionPane.showInputDialog(this, "Selecione a quantidade máxima de arestas.", (String) filterComboBox.getSelectedItem(), JOptionPane.INFORMATION_MESSAGE, null, options, "1");
                
                if(option != null)
                {
                    int sourceRm = Integer.valueOf(baseRm);
                    int maxDeep = Integer.valueOf(option);
                    
                    List<List<GraphVertex>> touchableVertexes = graphManager.calculateTouchableVertexes(sourceRm, maxDeep);
                
                    String log = "Limite: " + maxDeep + "\nA partir de: " + sourceRm + "\nContatado(s): ";
                    
                    int totalTouchableVertexesCounter = 0;

                    if(touchableVertexes.isEmpty())
                    {
                        log += "nenhum RM contatado";   
                    }
                    else
                    {
                        for(int i = 0, iLen = touchableVertexes.size(); i < iLen; i++)
                        {
                            for(int j = 0, jLen = touchableVertexes.get(i).size(); j < jLen; j++)
                            {   
                                totalTouchableVertexesCounter++;
                                
                                log += touchableVertexes.get(i).get(j).getRm();

                                if(i < iLen - 1 || j < jLen - 1)
                                {
                                    log += ", ";
                                }
                            }
                        }
                    }
                    
                    log += "\nTotal: " + totalTouchableVertexesCounter + " contatado(s)";
                    
                    log += "\n\n---------------------Profundade (cor) - Legenda---------------------";
                    log += "\n                           Nivel 1 = Verde";
                    log += "\n                           Nivel 2 = Azul";
                    log += "\n                           Nivel 3 = Roza";
                    log += "\n                          Nivel 4 = Laranja";
                    log += "\n                          Nivel 5 = Vermelho";

                    log((String) filterComboBox.getSelectedItem(), log);
                }
                else
                {
                    removeFilter("Ação desfeita.");
                }
            }
            else
            {
                removeFilter();
            }
        }
    }//GEN-LAST:event_filterComboBoxActionPerformed

    private void baseRmTextFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_baseRmTextFieldActionPerformed
        // TODO add your handling code here:
    }//GEN-LAST:event_baseRmTextFieldActionPerformed

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JLabel baseRmLabel;
    private javax.swing.JTextField baseRmTextField;
    private javax.swing.JComboBox filterComboBox;
    private javax.swing.JLabel filterLabel;
    private javax.swing.JPanel graphPanel;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTextArea logTextArea;
    // End of variables declaration//GEN-END:variables
}
